import { ObjectSystemAttribute, FriendOf, ExpandOf, GetTypeOf, GetCustomAttributes } from "../../../../../Decorator/Decorator";
import { ConsoleComponent } from "../../../../Model/Share/Module/Console/ConsoleComponent";
import { AwakeSystem } from "../../../../../Core/Module/EventSystem/IAwakeSystem";
import { LoadSystem } from "../../../../../Core/Module/EventSystem/ILoadSystem";
import { ETTask } from "../../../../../Support/Share/Lib/Async/ETTask";
import { EventSystem } from "../../../../../Core/Module/EventSystem/EventSystem";
import { ConsoleHandlerAttribute } from "../../../../Model/Share/Module/Console/ConsoleHandlerAttribute";
import { IConsoleHandler } from "../../../../Model/Share/Module/Console/IConsoleHandler";
import { Exception } from "../../../../../Core/Object/Exception";

/**
 * 使用 Expand 扩展方法
 * 
 * 必须作出以下申明，才能调用对象的扩展方法
 */
declare module "../../../../Model/Share/Module/Console/ConsoleComponent" {

    interface ConsoleComponent {
        Load(): void;
        Start(): Promise<any>;
    }

}

@ExpandOf(ConsoleComponent)
export class ConsoleComponentSystem {

    private static Load(self: ConsoleComponent): void {
        self.Handlers.Clear();

        let types = EventSystem.Instance.GetTypes(GetTypeOf(ConsoleHandlerAttribute));
        for (let type in types) {
            let clazz = types[type];
            let attrs = GetCustomAttributes(clazz);
            if (attrs.length == 0) {
                continue;
            }
            let consoleHandlerAttribute = <ConsoleHandlerAttribute>attrs[0];
            let obj = new clazz();
            let iConsoleHandler = obj as IConsoleHandler;
            if (iConsoleHandler == null) {
                throw new Exception(`ConsoleHandler handler not inherit IConsoleHandler class: ${GetTypeOf(obj)}`);
            }
            self.Handlers.Add(consoleHandlerAttribute.Mode, iConsoleHandler);
        }
    }

    private static async Start(self: ConsoleComponent): Promise<any> {
        // self.CancellationTokenSource = new CancellationTokenSource();

        // while (true) {
        //     try {
        //             ModeContex modeContex = self.GetComponent<ModeContex>();
        //             string line = await Task.Factory.StartNew(() => {
        //         Console.Write($"{modeContex?.Mode ?? ""}> ");
        //         return Console.In.ReadLine();
        //     }, self.CancellationTokenSource.Token);

        //         line = line.Trim();

        //         switch (line) {
        //             case "":
        //                 break;
        //             case "exit":
        //                 self.RemoveComponent<ModeContex>();
        //                 break;
        //             default:
        //                 {
        //                     string[] lines = line.Split(" ");
        //                     string mode = modeContex == null ? lines[0] : modeContex.Mode;

        //                     if (!self.Handlers.TryGetValue(mode, out IConsoleHandler iConsoleHandler)) {
        //                         Log.Console($"not found command: {line}");
        //                         break;
        //                     }

        //                     if (modeContex == null) {
        //                         modeContex = self.AddComponent<ModeContex>();
        //                         modeContex.Mode = mode;
        //                     }
        //                     await iConsoleHandler.Run(modeContex, line);
        //                     break;
        //                 }
        //         }
        //     }
        //     catch (Exception e)
        //     {
        //         Log.Console(e.toString());
        //     }
        // }
    }

}

@FriendOf(ConsoleComponent)
@ObjectSystemAttribute()
export class ConsoleComponentAwakeSystem extends AwakeSystem<ConsoleComponent> {

    Awake(self: ConsoleComponent): void {
        self.Load();

        self.Start().then();
    }

}

@FriendOf(ConsoleComponent)
@ObjectSystemAttribute()
export class ConsoleComponentLoadSystem extends LoadSystem<ConsoleComponent> {

    Load(self: ConsoleComponent): void {
        self.Load();
    }

}